package pers.zifeng.distributed.lock.mysql.service;

import lombok.extern.slf4j.Slf4j;
import pers.zifeng.distributed.lock.utils.JDBCUtils;

import java.lang.management.ManagementFactory;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * @author: zf
 * @date: 2021/05/14 16:49:01
 * @version: 1.0.0
 * @description: mysqlLock类
 */
@Slf4j
public class MysqlDistributedLockService {

    private static Connection connection;
    private static Statement statement;
    private static ResultSet resultset;

    static {
        try {
            connection = JDBCUtils.getConnection();
            statement = connection.createStatement();
            resultset = null;
        } catch (SQLException e) {
            log.error("连接数据库失败！", e);
        }
    }

    /**
     * 锁表-获取锁
     *
     * @param resource    资源
     * @param description 锁描述
     * @return 是否操作成功
     */
    public static boolean tryLock(int resource, String description) {
        String sql = "insert into database_lock (resource,description) values (" + resource + ",'" + description + "');";
        try {
            //获取数据库连接
            int stat = statement.executeUpdate(sql);
            return stat == 1;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 锁表-释放锁
     *
     * @param resource 资源
     * @return 释放情况
     */
    public static boolean releaseLock(int resource) throws SQLException {
        String sql = "delete from database_lock where resource=" + resource;

        //获取数据库连接
        int stat = statement.executeUpdate(sql);
        return stat == 1;
    }

    /**
     * 乐观锁-开启事务自动提交
     *
     * @throws SQLException 错误
     */
    public static void AutoCommit() {
        try {
            connection.setAutoCommit(true);
        } catch (SQLException sqlException) {
            log.error("开启自动提交失败！", sqlException);
        }
    }

    /**
     * 乐观锁-获取资源
     *
     * @param id 资源id
     * @return resultSet
     */
    public static ResultSet getGoodCount(int id) throws SQLException {
        String sql = "select * from database_lock_2 where id=" + id;

        //获取数据库连接
        resultset = statement.executeQuery(sql);
        return resultset;

    }

    /**
     * 乐观锁-修改资源
     *
     * @param id        资源id
     * @param goodCount 资源
     * @return 修改状态
     */
    public static boolean setGoodCount(int id, int goodCount) throws SQLException {
        String sql = "update database_lock_2 set good_count = good_count-1 where id=" + id + " and good_count=" + goodCount;

        //获取数据库连接
        int stat = statement.executeUpdate(sql);
        return stat == 1;
    }

    /**
     * 悲观锁-获取锁资源
     *
     * @param id 资源id
     * @return 资源
     */
    public static ResultSet getGoodCount2(int id) throws SQLException {
        String sql = "select * from database_lock_2 where id=" + id + " for update";
        //获取数据库连接
        resultset = statement.executeQuery(sql);
        return resultset;
    }

    /**
     * 悲观锁-修改资源
     *
     * @param id 资源id
     * @return 修改状态
     */
    public static boolean setGoodCount2(int id) throws SQLException {
        String sql = "update database_lock_2 set good_count = good_count-1 where id=" + id;
        //获取数据库连接
        int stat = statement.executeUpdate(sql);
        return stat == 1;
    }

    /**
     * 悲观锁-关闭事务自动提交
     */
    public static void forBidAutoCommit() {
        try {
            connection.setAutoCommit(false);
        } catch (SQLException sqlException) {
            log.error("关闭自动提交失败!", sqlException);
        }
    }

    /**
     * 悲观锁-提交事务
     */
    public static void commit(String pid, String goodName, int goodCount) throws SQLException {
        connection.commit();
        log.info("当前线程:" + pid + " 抢购商品:" + goodName + "成功,剩余库存为:" + (goodCount - 1));

    }

    /**
     * 悲观锁-回滚
     *
     * @throws SQLException 错误
     */
    public static void rollBack() throws SQLException {
        connection.rollback();
    }

    public static void close() {
        log.info("当前线程:" + ManagementFactory.getRuntimeMXBean().getName().split("@")[0] + ",关闭了数据库连接！");
        JDBCUtils.close(resultset, statement, connection);
    }

}
